'use strict';
const fs = require('fs');
const path = require('path');
const sendToWormhole = require('stream-wormhole');
const Controller = require('egg').Controller;

module.exports = app => {
  return class UploadController extends Controller {
    async uploadPage() {
      const ctx = this.ctx;
      const query = ctx.query;
      if (query.folderId) {
        ctx.locals = {
          folder: await this.service.folder.selectById(+query.folderId)
        };
      }
      await ctx.render('admin/resource/upload.html');
    }

    // TODO: 文件大小限制，格式限制，目前即使限制文件依然会被上传
    // 上传文件
    async uploadJson() {
      const ctx = this.ctx;
      const stream = await ctx.getFileStream();
      const fileInfo = fileHandler(app.config.baseDir, stream);
      this.logger.warn('Saving %s to %s', stream.filename, fileInfo.filepath);
      // 处理文件相关信息
      let text = '';
      try {
        await saveStream(stream, fileInfo.filepath);
        await this.service.resource.create({
          name: fileInfo.filename,
          // url: `/public/upload/${fileInfo.year}/${fileInfo.month}/${fileInfo.savename}`,
          url: `/public/upload/${fileInfo.year}/${fileInfo.month}/${
            stream.filename
          }`,
          type: getFileType(fileInfo.filename, app.config.resourceType),
          folder_id: ctx.request.header.folderid
            ? ctx.request.header.folderid
            : 0,
          size: fileInfo.size,
          mime: fileInfo.mime,
          create_time: new Date(),
          modify_time: new Date()
        });
      } catch (err) {
        await sendToWormhole(stream); // 没保存成功也要消化掉文件流否则会造成浏览器无法响应
        throw err;
      }

      // ctx.body = text;
      ctx.body = {
        code: 0,
        msg: '',
        data: {
          src: `${ctx.protocol}://${ctx.host}/public/upload/${fileInfo.year}/${
            fileInfo.month
          }/${stream.filename}`,
          title: `${fileInfo.name}`
        }
      };
    }
  };
};

function saveStream(stream, filepath) {
  return new Promise((resolve, reject) => {
    if (filepath.indexOf('/read-error-') > 0) {
      stream.once('readable', () => {
        const buf = stream.read(10240);
        console.log('read %d bytes', buf.length);
        setTimeout(() => {
          reject(new Error('mock read error'));
        }, 1000);
      });
    } else {
      const ws = fs.createWriteStream(filepath);
      stream.pipe(ws);
      ws.on('error', reject);
      ws.on('finish', resolve);
    }
  });
}

// 处理文件相关信息
function fileHandler(baseDir, stream) {
  // 时间
  let now = new Date();
  let year = now.getFullYear();
  let month = now.getMonth() + 1;

  // 路径
  const uploadPath = path.join(baseDir, `app/public/upload`);
  const fileYearPath = path.join(uploadPath, `/${year}`);
  const fileMonthPath = path.join(fileYearPath, `/${month}`);
  if (!fs.existsSync(uploadPath)) {
    fs.mkdirSync(uploadPath);
    if (!fs.existsSync(fileYearPath)) {
      fs.mkdirSync(fileYearPath);
      if (!fs.existsSync(fileMonthPath)) {
        fs.mkdirSync(fileMonthPath);
      }
    }
  }

  // let prefix = stream.filename.split('.');
  // prefix = prefix[prefix.length - 1];
  // let filename = getRandom() + new Date().getTime() + '.' + prefix;
  // const filepath = path.join(fileMonthPath, `/${filename}`);
  const filepath = path.join(fileMonthPath, `/${stream.filename}`);
  return {
    year: year,
    month: month,
    filepath: filepath,
    size: stream.fields.size,
    mime: stream.mime,
    filename: stream.filename
    // savename: filename //保存时的名字
  };
}

function getRandom(len = 20) {
  const str = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
  let ret = '';
  for (let i = 0; i < len; i++) {
    ret += str[Math.round(Math.random() * (str.length - 1))];
  }
  return ret;
}

// 判断文件的后缀名返回类型
// IMG: 1,//图片类型
// DOC:2,//文档类型
// VIDEO: 3 //文档类型
// ZIP: 4
// VOICE: 5
function getFileType(filename, config) {
  const suffixs = filename.split('.');
  const suffix = suffixs[suffixs.length - 1];
  if ('gif,jpg,jpeg,bmp,png,wbmp,webp'.indexOf(suffix) > -1) return config.IMG;
  else if ('txt,xls,ppt,doc,pptx,docx,xlsx,pdf'.indexOf(suffix) > -1) {
    return config.DOC;
  } else if ('mp4,avi,m4v,ogv,webm'.indexOf(suffix) > -1) return config.VIDEO;
  else if ('zip,gz,tgz,gzip'.indexOf(suffix) > -1) return config.ZIP;
  else if ('mp3,ogg'.indexOf(suffix) > -1) return config.VOICE;
}
